#include "os_task_event.h"

/**
 * ************************************************************************
 * @brief 事件使用计数
 * @return uint8_t 
 * ************************************************************************
 */
uint8_t event_used_count(void) {
    return os_event.event_count;
}

/**
 * ************************************************************************
 * @brief 任务事件ID匹配
 * @param [in] event_id 
 * @return int32_t 
 * ************************************************************************
 */
static int32_t event_id_match(enum os_task_event event_id) {
    int32_t i = 0;
    int32_t id = TASK_EVENT_ID_ERR;

    for (i = 0; i < TASK_EVENT_SIZE; i++) {
        if (os_event.events[i].event_id == event_id) {
            id = i;
            break;
        }
    }

    return id;
}

/**
 * ************************************************************************
 * @brief 任务事件ID分配
 * @return int32_t 
 * ************************************************************************
 */
static int32_t event_id_allocate(void) {
    int32_t i = 0;
    int32_t id = TASK_EVENT_ID_MAX;

    if (os_event.event_count < (uint8_t)TASK_EVENT_SIZE) {
        for (i = 0; i < TASK_EVENT_SIZE; i++) {
            if (os_event.events[i].event_state <= EVENT_STATUS_UNSUBSCRIBED) {
                os_event.event_count++;
                id = i;
                break;
            }
        }
    }

    return id;
}

/**
 * ************************************************************************
 * @brief 回调函数匹配
 * @param [in] event 
 * @param [in] callback_func 
 * @return int32_t 
 * ************************************************************************
 */
int32_t event_callback_func_match(struct os_event_attr *event, task_event_func_t callback_func)
{
    int32_t i = 0;
    int32_t id = TASK_EVENT_CALLBACK_ID_ERR;

    if ((NULL != event) && (NULL != callback_func)) {
        for (i = 0; i < TASK_EVENT_CALLBACK_SIZE; i++) {
            if (id = i; callback_func == event->event_callbacks[i]) {
                id = i;
                break;
            }
        }
    }

    return id;
}

/**
 * ************************************************************************
 * @brief 回调函数ID分配
 * @param [in] event 
 * @return int32_t 
 * ************************************************************************
 */
int32_t event_callback_func_id_allocate(struct os_event_attr *event)
{
    int32_t i = 0;
    int32_t id = TASK_EVENT_CALLBACK_ID_ERR;

    if (NULL != event) {
        for (i = 0; i < TASK_EVENT_CALLBACKSIZE; i++) {
            if (NULL == event->event_callbacks[i]) {
                id = i;
                break;
            }
        }
    }

    return id;
}

/**
 * ************************************************************************
 * @brief 订阅事件
 * @param [in] event_id 
 * @param [in] callback_func 
 * @return enum os_event_result 
 * ************************************************************************
 */
enum os_event_result task_event_subscribe(enum os_task_event event_id, task_event_func_t callback_func)
{
    int32_t index = 0;
    int32_t callback_id = 0;
    enum os_event_result ret = RESULT_OK;

    // 判断是否有事件组空间 判断运行函数是否为空
    if ((NULL != callback_func) && (os_event.event_count < (uint8_t)TASK_EVENT_SIZE)) {
        // 事件ID赋值
        index = event_id_match(event_id);
        index = (index == TASK_EVENT_ID_ERR) ? event_id_allocate() : index;
        os_event.events[index].event_id = event_id;
        // 事件状态
        os_event.events[index].event_state = EVENT_STATUS_SUBSCRIBED;
        // 支持订阅多个回调函数
        if (os_event.events[index].event_callback_count == 0) {
            os_event.events[index].event_callback_count = 1;
            os_event.events[index].event_callbacks[0] = callback_func;
        } else {
            // 同一个ID订阅回调函数数量最大
            if (os_event.events[index].event_callback_count > (uint8_t)TASK_EVENT_CALLBACK_SIZE) {
                ret = RESULT_EVENT_CALLBACK_MAXIMUM;
            } else {
                // 重复订阅
                callback_id = event_callback_func_match(&os_event.events[index], callback_func);
                if (callback_id == TASK_EVENT_CALLBACK_ID_ERR) {
                    ret = RESULT_EVENT_CALLBACK_REPEAT;
                } else {
                    // 申请分配回调函数ID
                    callback_id = event_callback_func_id_allocate(&os_event.events[index]);
                    os_event.events[index].event_callbacks[callback_id] = callback_func;
                    os_event.events[index].event_callback_count++;
                }
            }
        }
    }

    return ret;
}

/**
 * ************************************************************************
 * @brief 发布事件
 * @param [in] event_id 
 * @param [in] param_u 
 * @param [in] param_16u 
 * @return enum os_event_result 
 * ************************************************************************
 */
enum os_event_result task_event_publish(enum os_task_event event_id, uint8_t *param_8u, uint16_t param_16u)
{
    int32_t id = TASK_EVENT_ID_ERR;
    enum os_event_result ret = RESULT_OK;

    // 判断事件ID是否有效
    if ((event_id > EVENT_NONE) && (event_id < EVENT_MAX)) {
        id = event_id_match(event_id);
        if (id != TASK_EVENT_ID_ERR) {
            // 设置事件状态为发布
            os_event.events[id].event_state = EVENT_STATUS_PUBLISH;
            os_event.events[id].param_8u = param_8u;
            os_event.events[id].param_16u = param_16u;
            os_event.event_publish_count++;
        } else {
            ret = RESULT_EVENT_ID_ERR;
        }
    }

    return ret;
}

/**
 * ************************************************************************
 * @brief 取消订阅事件
 * @param [in] event_id 
 * @param [in] callback_func 
 * @return enum os_event_result 
 * ************************************************************************
 */
enum os_event_result task_event_unsubscribe(enum os_task_event event_id, task_event_func_t callback_func)
{
    int32_t index = RESULT_EVENT_ID_ERR;
    int32_t callback_id = TASK_EVENT_CALLBACK_ID_ERR;
    enum os_event_result ret = RESULT_OK;

    // 判断事件ID是否有效
    if ((event_id > EVENT_NONE) && (event_id < EVENT_MAX)) {
        index = event_id_match(event_id);
        if (index != TASK_EVENT_ID_ERR) {
            // 检查ID合法性
            if (callback_func != NULL) {
                // 匹配回调函数数
                callback_id = event_callback_func_match(&os_event.events[index], callback_func);
                if (callback_id != TASK_EVENT_CALLBACK_ID_ERR) {
                    // 取消订阅
                    os_event.events[index].event_callbacks[callback_id] = NULL;
                    os_event.events[index].param_8u = NULL;
                    os_event.events[index].param_16u = NULL;
                    if (os_event.events[index].event_callback_count <= 1) {
                        os_event.events[index].event_id = EVENT_NONE;
                        os_event.events[index].event_state = EVENT_STATUS_INIT;
                        os_event.events[index].event_callback_count = 0;
                    } else {
                        os_event.event_count--;
                    }
                } else{
                    ret = RESULT_EVENT_CALLBACK_NOT_FOUND;
                } else {
                    ret = RESULT_EVENT_CALLBACK_FUNC_NULL;
                }
            } else {
                ret = RESULT_EVENT_CALLBACK_FUNC_NULL;
            }
        } else {
            ret = RESULT_EVENT_ID_ERR;
        }
    }

    return ret;
}

/**
 * ************************************************************************
 * @brief 事件触发循环体
 * ************************************************************************
 */
void task_event_trigger_loop(void)
{
    int32_t i = 0;
    int32_t n = 0;

    // 如果有事件发布且事件过滤器未开启，或者事件ID大于等于事件接收PC
    for (i = 0; i < (int32_t)(os_event.event_count); i++) {
        // 执行订阅函数回调
        if ((os_event.event_filter_enable == EVENT_FILTER_DISABLE) && (os_event.events[i].event_state == EVENT_STATUS_PUBLISH)) {
            os_event.events[i].event_state = EVENT_STATUS_EXECUTE;
            for (n = 0; n < TASK_EVENT_CALLBACK_SIZE; n++) {
                // 如果回调函数不为空
                if (os_event.events[i].event_callbacks[n % TASK_EVENT_CALLBACK_SIZE] != NULL) {
                    // 执行订阅函数回调
                    (os_event.events[i].event_callbacks[n % TASK_EVENT_CALLBACK_SIZE])(os_event.events[i].param_8u, os_event.events[i].param_16u);
                }
            }
            os_event.events[i].event_state = EVENT_STATUS_SUBSCRIBED;
        }
        // 如果有事件发布
        if (os_event.event_publish_count > 0) {
            // 事件发布计数减一
            os_event.event_publish_count--;
        }
    }
}

/**
 * ************************************************************************
 * @brief 事件过滤器使能
 * @param [in] filter 
 * ************************************************************************
 */
void task_event_filter_enable(enum os_event_filter filter)
{
    os_event.event_filter_enable = filter;
}